package com.kefu.call.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.kefu.basic.mapper.BasicStatusConfigMapper;
import com.kefu.basic.model.BasicStatusConfig;
import com.kefu.call.mapper.*;
import com.kefu.call.model.*;
import com.kefu.call.vo.*;
import com.kefu.common.context.KefuContext;
import com.kefu.common.service.AbstractKefuService;
import com.kefu.common.util.BigDecimalUtil;
import com.kefu.common.util.DateUtils;
import com.kefu.common.util.DivUtil;
import com.kefu.common.util.JacksonUtil;
import com.kefu.sys.mapper.SysGroupMapper;
import com.kefu.sys.mapper.SysUserGroupMapper;
import com.kefu.sys.mapper.SysUserMapper;
import com.kefu.sys.model.SysGroup;
import com.kefu.sys.model.SysUser;
import com.kefu.sys.model.SysUserGroup;
import com.kefu.sys.vo.SysUserSearchVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class CallStatisticsService extends AbstractKefuService<CallMakeCall> {
    @Resource
    private AgentAuxMapper agentAuxMapper;
    @Resource
    private AgentIdeMapper agentIdeMapper;
    @Resource
    private SysGroupMapper sysGroupMapper;
    @Resource
    private CallStartMapper callStartMapper;
    @Resource
    private CallMakeCallMapper callMakeCallMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysUserGroupMapper sysUserGroupMapper;
    @Resource
    private CallUserStatusMapper callUserStatusMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate1;
    @Resource
    private BasicStatusConfigMapper basicStatusConfigMapper;
    private static final String CALL_QUEUE_GROUP = "call_queue_group:";


    @SuppressWarnings("unchecked")
    public Page<CallAgentWorkLoadVo> callWorkloadList(CallAgentWorkLoadSearchVo param) {
        Page page = new Page<>(param.getPageNo(), param.getPageSize(), param.getPageSize() <= 100);
        SysUserSearchVo search = new SysUserSearchVo();
        search.setGroupType(1);
        search.setTenantId(KefuContext.getTid());
        if (StrUtil.isNotBlank(param.getAdminId())) {
            search.setUserIds(Arrays.asList(param.getAdminId().split(",")));
        } else {
            if (StrUtil.isNotBlank(param.getGroupId())) {
                search.setGroupIds(Arrays.asList(param.getGroupId().split(",")));
            }
        }
        Page<SysUser> users = sysUserMapper.search(page, search);
        if (CollUtil.isEmpty(users.getRecords())) {
            return (Page<CallAgentWorkLoadVo>) page.convert(map -> new CallAgentWorkLoadVo());
        }
        String endTime = DateUtil.format(new Date(param.getQueryTimeEnd()), "yyyy-MM-dd HH:mm:ss");
        Map<String, Object> staticQuery = Maps.newHashMap();
        staticQuery.put("startTime", DateUtil.beginOfDay(DateUtil.date(param.getQueryTimeStart())));
        staticQuery.put("endTime", new Date(param.getQueryTimeEnd()));
        staticQuery.put("tenantId", KefuContext.getTid());
        if (Timestamp.valueOf(endTime).getTime() > DateUtil.beginOfDay(new Date()).getTime()) {
            staticQuery.put("today", true);
        }
        List<Map<String, Object>> callIns = callStartMapper.staticsCallInList(staticQuery);
        List<Map<String, Object>> callOuts = callMakeCallMapper.staticsCallOutList(staticQuery);
        List<Map<String, Object>> agentIdes = agentIdeMapper.staticsIdeList(staticQuery);
        List<BasicStatusConfig> basicStatusConfigs = callAgentStatusTitle();
        List<CallAgentWorkLoadVo> workList = users.getRecords().stream().map(user -> {
            CallAgentWorkLoadVo workVo = new CallAgentWorkLoadVo();
            String agentId = user.getUserId();
            workVo.setAgentId(agentId);
            workVo.setAgentName(user.getUserName());
            workVo.setReceiveNum(user.getReceiveNum());
            return workVo;
        })
        .peek(vo -> {
            AtomicLong onlineTime = new AtomicLong();
            List<CallAgentAuxWorkLoadVo> callAgentAuxWorkLoadVoList = Lists.newArrayList();
            agentIdes.stream().filter(ides -> vo.getAgentId().equals(ides.get("agentid"))).findAny()
            .ifPresent(ides -> {
                if (ides.get("idetime") != null) {
                    long idetime = BigDecimalUtil.get(ides.get("idetime")).longValue();
                    vo.setIdeTime(idetime);
                    onlineTime.addAndGet(idetime);
                }
            });
            basicStatusConfigs.forEach(config -> {
                String statusCode = config.getStatusCode();
                staticQuery.put("agentId", vo.getAgentId());
                staticQuery.put("statusCode", Convert.toInt(statusCode));
                List<Map<String, Object>> agentAux = agentAuxMapper.staticsAgentAux(staticQuery);
                CallAgentAuxWorkLoadVo workLoadVo = new CallAgentAuxWorkLoadVo();
                if (CollUtil.isNotEmpty(agentAux)) {
                    long auxtime = BigDecimalUtil.get(agentAux.get(0).get("auxtime")).longValue();
                    onlineTime.addAndGet(auxtime);
                    workLoadVo.setStatusCode(statusCode);
                    workLoadVo.setAuxtime(auxtime);
                    callAgentAuxWorkLoadVoList.add(workLoadVo);
                }
            });
            vo.setOnlineTime(onlineTime.longValue());
            vo.setCallAgentAuxWorkLoadVoList(callAgentAuxWorkLoadVoList);
        })
        .peek(workVo -> callOuts.stream().filter(map -> workVo.getAgentId().equals(map.get("agentid")))
            .findAny()
            .ifPresent(out -> {
                Long outCallNumber = (Long) out.get("outcallnumber");
                BigDecimal outCallFailNumber = BigDecimalUtil.get(out.get("outcallfailnumber"));
                BigDecimal outCallSuccessNumber = BigDecimalUtil.get(out.get("outcallsuccessnumber"));
                BigDecimal outCallTalkTime = BigDecimalUtil.get(out.get("outcalltalktime"));
                BigDecimal outCallHoldNumber = BigDecimalUtil.get(out.get("outcallholdnumber"));
                BigDecimal outCallHoldTime = BigDecimalUtil.get(out.get("outcallholdtime"));
                workVo.setOutCallNumber(outCallNumber.intValue());
                workVo.setOutCallFailNumber(outCallFailNumber.intValue());
                workVo.setOutCallSuccessNumber(outCallSuccessNumber.intValue());
                workVo.setOutCallTalkTime(outCallTalkTime.intValue());
                workVo.setOutCallTalkTimeAvg(DivUtil.div(outCallTalkTime.longValue(), outCallSuccessNumber.intValue()));
                workVo.setOutCallHoldNumber(outCallHoldNumber.intValue());
                workVo.setOutCallHoldTime(outCallHoldTime.longValue());
            }))
        .peek(workVo -> callIns.stream().filter(map -> workVo.getAgentId().equals(map.get("agentid"))).findAny()
            .ifPresent(in -> {
                BigDecimal callInNumber = BigDecimalUtil.get(in.get("callinnumber"));
                BigDecimal callInGroupNumber = BigDecimalUtil.get(in.get("callingroupnumber"));
                BigDecimal agentNoAnswerNumber = BigDecimalUtil.get(in.get("agentnoanswernumber"));
                BigDecimal agentAnswerNumber = BigDecimalUtil.get(in.get("agentanswernumber"));
                BigDecimal agentAnswer15Number = BigDecimalUtil.get(in.get("agentanswer15number"));
                BigDecimal callInTalkTime = BigDecimalUtil.get(in.get("callintalktime"));
                BigDecimal callInHoldNumber = BigDecimalUtil.get(in.get("callinholdnumber"));
                BigDecimal callInHoldTime = BigDecimalUtil.get(in.get("callinholdtime"));
                BigDecimal onceSolveNumber = BigDecimalUtil.get(in.get("oncesolvenumber"));
                workVo.setCallInNumber(callInNumber.intValue());
                workVo.setCallInGroupNumber(callInGroupNumber.intValue());
                workVo.setAgentNoAnswerNumber(agentNoAnswerNumber.intValue());
                workVo.setAgentAnswerNumber(agentAnswerNumber.intValue());
                workVo.setAgentAnswer15Number(agentAnswer15Number.intValue());
                workVo.setCallInTalkTime(callInTalkTime.longValue());
                workVo.setCallInHoldNumber(callInHoldNumber.intValue());
                workVo.setCallInHoldTime(callInHoldTime.longValue());
                workVo.setOnceSolveNumber(onceSolveNumber.longValue());
                workVo.setCallInTalkTimeAvg(DivUtil.div(callInTalkTime.longValue(), agentAnswerNumber.intValue()));
        }))
        .peek(workVo -> {
            workVo.setOnlineTime(workVo.getOnlineTime() + workVo.getCallInTalkTime());
        })
        .peek(vo -> vo.getCallAgentAuxWorkLoadVoList().forEach(workLoadVo -> workLoadVo.setAuxRatio(
                DivUtil.percent(workLoadVo.getAuxtime(), vo.getOnlineTime()) == null ? "0" : DivUtil.percent(workLoadVo.getAuxtime(), vo.getOnlineTime()))))
        .collect(Collectors.toList());
        page.setRecords(workList);
        page.setPages(users.getPages());
        page.setPages(users.getPages());
        page.setTotal(users.getTotal());
        page.setCurrent(users.getCurrent());
        return page;
    }
    public CallOverviewVo callOverview(CallOverviewSearchVo param) {
        String endTime = DateUtil.format(new Date(param.getQueryTimeEnd()), "yyyy-MM-dd HH:mm:ss");
        String startTime = DateUtil.format(new Date(param.getQueryTimeStart()), "yyyy-MM-dd HH:mm:ss");
        Map<String, Object> queryParam = Maps.newHashMap();
        queryParam.put("startTime", Timestamp.valueOf(startTime));
        queryParam.put("endTime", Timestamp.valueOf(endTime));
        queryParam.put("tenantId", KefuContext.getTid());
        queryParam.put("agent", "");
        queryParam.put("agentList", param.getAgentList());
        queryParam.put("gatewayNumberList", param.getGatewayNumberList());
        Map<String, Object> result1 = callMakeCallMapper.callOverview(queryParam);
        Map<String, Object> result2 = callStartMapper.callOverview(queryParam);
        result2.putAll(result1);
        CallOverviewVo workVo = BeanUtil.toBean(result2, CallOverviewVo.class, CopyOptions.create().ignoreCase());
        List<Map<String, Object>> repeat24Call = callStartMapper.callIn24RepeatCall(queryParam);
        if (CollUtil.isNotEmpty(repeat24Call)) {
            workVo.setRepeat24Call(repeat24Call.stream()
                    .filter(map -> Convert.toInt(map.get("callnum")) > 1 ).count());
        }
        logger.info("呼叫概览:{}", JacksonUtil.toString(workVo));
        workVo.setOutCallTalkTimeAvg(DivUtil.div(workVo.getOutCallTalkTime(), workVo.getOutCallSuccessNumber()));
        workVo.setCallInTalkTimeAvg(DivUtil.div(workVo.getCallInTalkTime(), workVo.getAgentAnswerNumber()));
        return workVo;
    }


    public List<CallOverviewVo> callOverviewTrend(CallOverviewSearchVo param) {
        String endTime = DateUtil.format(new Date(param.getQueryTimeEnd()), "yyyy-MM-dd HH:mm:ss");
        String startTime = DateUtil.format(new Date(param.getQueryTimeStart()), "yyyy-MM-dd HH:mm:ss");
        String endDay = DateUtil.format(new Date(param.getQueryTimeEnd()), "yyyy-MM-dd");
        String startDay = DateUtil.format(new Date(param.getQueryTimeStart()), "yyyy-MM-dd");

        Map<String, Object> queryParam = Maps.newHashMap();
        queryParam.put("startTime", Timestamp.valueOf(startTime));
        queryParam.put("endTime", Timestamp.valueOf(endTime));
        queryParam.put("tenantId", KefuContext.getTid());
        queryParam.put("agent", "");

        queryParam.put("groupType", "date");
        if (startDay.equals(endDay)) {
            queryParam.put("groupType", "hour");
        }

        List<Map<String, Object>> callouts = callMakeCallMapper.callOverviewTrend(queryParam);
        List<Map<String, Object>> callIns = callStartMapper.callOverviewTrend(queryParam);

        Set<String> resultDates = Stream.concat(callouts.stream(), callIns.stream())
                .map(map -> (String) map.get("resultdate"))
                .collect(Collectors.toSet());

        return resultDates.stream()
                .sorted()
                .map(date -> {
                    Map<String, Object> map = Maps.newHashMap();
                    map.put("resultdate", date);
                    return map;
                }).peek(map -> {
                    callouts.stream()
                            .filter(data -> data.get("resultdate").equals(map.get("resultdate")))
                            .findAny()
                            .ifPresent(map::putAll);

                    callIns.stream()
                            .filter(data -> data.get("resultdate").equals(map.get("resultdate")))
                            .findAny()
                            .ifPresent(map::putAll);

                }).map(map -> BeanUtil.toBean(map, CallOverviewVo.class, CopyOptions.create().ignoreCase())).peek(workVo -> {
                    workVo.setOutCallSuccessRatio(DivUtil.percent(workVo.getOutCallSuccessNumber(), workVo.getOutCallNumber()));
                    workVo.setOutCallTalkTimeAvg(DivUtil.div(workVo.getOutCallTalkTime(), workVo.getOutCallSuccessNumber()));
                    workVo.setAgentAnswerRatio(DivUtil.percent(workVo.getAgentAnswerNumber(), workVo.getCallInTotal()));
                    workVo.setAgentAnswer15Ratio(DivUtil.percent(workVo.getAgentAnswer15Number(), workVo.getAgentAnswerNumber()));
                    workVo.setCallInTalkTimeAvg(DivUtil.div(workVo.getCallInTalkTime(), workVo.getAgentAnswerNumber()));
                }).peek(workVo -> {
                    String resultDate = workVo.getResultDate();
                    if (resultDate.length() != 10) {
                        workVo.setResultDate(resultDate.substring(0, 10));
                        workVo.setResultHour(resultDate.substring(11, 13) + ":00");
                    }
                })
                .collect(Collectors.toList());
    }

    public Page<CallAgentStatusVo> callAgentStatusList(CallAgentStatusSearchVo param) {
        String endTime = DateUtil.format(new Date(param.getQueryTimeEnd()), "yyyy-MM-dd HH:mm:ss");
        String startTime = DateUtil.format(new Date(param.getQueryTimeStart()), "yyyy-MM-dd HH:mm:ss");
        List<AgentIde> agentIdes = agentIdeMapper.selectList(Wrappers.lambdaQuery(AgentIde.class)
                .gt(AgentIde::getCreateStartTime, Timestamp.valueOf(startTime))
                .lt(AgentIde::getCreateStartTime, Timestamp.valueOf(endTime))
                .eq(AgentIde::getCompany, KefuContext.getTid())
                .in(StrUtil.isNotBlank(param.getAdminId()),
                        AgentIde::getAgentId, Lists.newArrayList(param.getAdminId().split(",")))
                .orderByDesc(AgentIde::getCreateStartTime)
                .last("limit 5000"));
        List<AgentAux> agentAuxes = agentAuxMapper.selectList(Wrappers.lambdaQuery(AgentAux.class)
                .gt(AgentAux::getCreateStartTime, Timestamp.valueOf(startTime))
                .lt(AgentAux::getCreateStartTime, Timestamp.valueOf(endTime))
                .eq(AgentAux::getCompany, KefuContext.getTid())
                .in(StrUtil.isNotBlank(param.getAdminId()),
                        AgentAux::getAgentId, Lists.newArrayList(param.getAdminId().split(",")))
                .orderByDesc(AgentAux::getCreateStartTime)
                .last("limit 5000"));
        Map<String, String> userNameMap = sysUserMapper.getUserNameMap(KefuContext.getTid());

        LambdaQueryWrapper configQuery=Wrappers.lambdaQuery(BasicStatusConfig.class)
                .eq(BasicStatusConfig::getStatusType,2)
                .eq(BasicStatusConfig::getStatus,1)
                .eq(BasicStatusConfig::getTenantId,KefuContext.getTid())
                .notIn(BasicStatusConfig::getStatusCode,"Logged Out","Available");//退出，空闲
        List<BasicStatusConfig> list=basicStatusConfigMapper.selectList(configQuery);
        Map<String,String> map=list.stream().collect(Collectors.toMap(BasicStatusConfig::getStatusCode,BasicStatusConfig::getStatusName));

        List<CallAgentStatusVo> statusVoList = new ArrayList<>();
        agentIdes.forEach(i -> {
            CallAgentStatusVo statusVo = new CallAgentStatusVo();
            statusVo.setAgentId(i.getAgentId());
            statusVo.setAgentName(userNameMap.get(i.getAgentId()));
            statusVo.setStatusStartTime(i.getCreateStartTime());
            statusVo.setStatusEndTime(i.getCreateEndTime());
            statusVo.setStatusType(1);
            statusVoList.add(statusVo);
        });
        agentAuxes.forEach(i -> {
            CallAgentStatusVo statusVo = new CallAgentStatusVo();
            statusVo.setAgentId(i.getAgentId());
            statusVo.setAgentName(userNameMap.get(i.getAgentId()));
            statusVo.setStatusStartTime(i.getCreateStartTime());
            statusVo.setStatusEndTime(i.getCreateEndTime());
            statusVo.setStatusType(2);
            statusVo.setAuxStatus(i.getAuxStatus());
            statusVo.setAuxName(map.get(String.valueOf(i.getAuxStatus())));
            statusVoList.add(statusVo);
        });
        List<CallAgentStatusVo> collect = statusVoList.stream().sorted(Comparator.comparing(CallAgentStatusVo::getStatusStartTime).reversed()).collect(Collectors.toList());
        Page<CallAgentStatusVo> page = new Page<>(param.getPageNo(), param.getPageSize());
        page.setTotal(collect.size());
        page.setRecords(collect.stream().skip((long) (param.getPageNo() - 1) * param.getPageSize()).limit(param.getPageSize()).collect(Collectors.toList()));

        return page;
    }

    public void exportCallAgentWorkload(CallAgentWorkLoadSearchVo param, HttpServletResponse response) throws IOException {
        param.setPageNo(1);
        param.setPageSize(1000);
        Page<CallAgentWorkLoadVo> callWorkloadList = callWorkloadList(param);
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("客服名称"), msg("外呼数量"), msg("外呼未接听"), msg("外呼接听"),
                msg("外呼接听率"), msg("呼入振铃"), msg("呼入未接听"), msg("呼入接听"),
                msg("呼入接听率"), msg("一次性解决数"), msg("呼入15秒接听数"), msg("呼入15秒接听率")
        };
        exportList.add(title);
        for (CallAgentWorkLoadVo i : callWorkloadList.getRecords()) {
            Object[] row = {i.getAgentName(), i.getOutCallNumber(), i.getOutCallFailNumber(), i.getOutCallSuccessNumber(),
                    i.getOutCallSuccessRatio(), i.getCallInNumber(), i.getAgentNoAnswerNumber(), i.getAgentAnswerNumber(),
                    i.getAgentAnswerRatio(), i.getOnceSolveNumber(), i.getAgentAnswer15Number(), i.getAgentAnswer15Ratio()
            };
            exportList.add(row);
        }
        csvWriter(exportList, response);
    }


    public List<CallUserStatus> callUserStatus(CallUserStatusSearchVo searchVo) {
        List<CallUserStatus> callUserStatuses = Lists.newArrayList();
        List<String> userIdList = Lists.newArrayList();
        if(StrUtil.isNotBlank(searchVo.getGroupId())){
            List<String> groups = Stream.of(searchVo.getGroupId().split(",")).collect(Collectors.toList());
            List<SysUserGroup> userGroups = sysUserGroupMapper.selectList(Wrappers.lambdaQuery(SysUserGroup.class).in(SysUserGroup::getGroupId,groups));
            if (CollUtil.isEmpty(userGroups)) {
                return callUserStatuses;
            }
            List<String> groupUsers = userGroups.stream()
                    .map(SysUserGroup::getUserId).distinct().collect(Collectors.toList());
            userIdList.addAll(groupUsers);
        }
        if (StrUtil.isNotBlank(searchVo.getAdminId())) {
            userIdList = Stream.of(searchVo.getAdminId().split(","))
                    .filter(StrUtil::isNotBlank).collect(Collectors.toList());
        }
        callUserStatuses = callUserStatusMapper.selectList(Wrappers.lambdaQuery(CallUserStatus.class)
                .eq(CallUserStatus::getCompany, KefuContext.getTid())
                .in(userIdList.size() > 0,CallUserStatus::getAgentId, userIdList));
        Map<String, String> userNameMap = sysUserMapper.getUserNameMap(KefuContext.getTid());
        callUserStatuses.forEach(item -> {
            item.setOnbreakval("用餐".equals(item.getOnbreakval()) ? "忙碌" : item.getOnbreakval());
            item.setAgentName(userNameMap.get(item.getAgentId()));
            item.setGroupList(sysGroupMapper.getByUserIdAndGroupType(item.getAgentId(), 1));
        });
        return callUserStatuses;

    }
    public CallUserStatusWrapper callUserStatus_v2(CallUserStatusSearchVo searchVo) {
        if(StrUtil.isNotBlank(searchVo.getGroupId())){
            List<String> groups=Stream.of(searchVo.getGroupId().split(",")).collect(Collectors.toList());
            List<SysUserGroup>userGroups=sysUserGroupMapper.selectList(Wrappers.lambdaQuery(SysUserGroup.class).in(SysUserGroup::getGroupId,groups));
            String users=userGroups.stream().map(SysUserGroup::getUserId).distinct().collect(Collectors.joining(","));
            searchVo.setAdminId(users);
        }
        List<String> users=Stream.of(searchVo.getAdminId().split(",")).filter(StrUtil::isNotBlank).collect(Collectors.toList());
        QueryWrapper query;
        if(users.size()>0){
            query=Wrappers.query().eq("Company", KefuContext.getTid())
                    .in("CCAgent",users);
        }else{
            query=Wrappers.query().eq("Company", KefuContext.getTid());
        }

        List<CallUserStatus> callUserStatuses = callUserStatusMapper.selectList(query);

        List<String> userIds=callUserStatuses.stream().map(CallUserStatus::getAgentId).distinct().collect(Collectors.toList());
        CallUserStatusStatistics statistics=new CallUserStatusStatistics();
        if(userIds.size()>0){
            Map<String, String> userNameMap = sysUserMapper.getUserNameMap(KefuContext.getTid());
            List<SysUserGroup>userGroups=sysUserGroupMapper.selectList(Wrappers.lambdaQuery(SysUserGroup.class).in(SysUserGroup::getUserId,userIds));
            List<String> groupIds=userGroups.stream().map(SysUserGroup::getGroupId).collect(Collectors.toList());
            List<SysGroup> groups=sysGroupMapper.selectBatchIds(groupIds);
            callUserStatuses.forEach(item -> {
                item.process();
                item.setAgentName(userNameMap.get(item.getAgentId()));
                List<SysGroup> subGroups=userGroups.stream().filter(ug->item.getAgentId().equals(ug.getUserId()))
                                    .map(SysUserGroup::getGroupId).distinct()
                                    .map(id->groups.stream().filter(g->g.getGroupId().equals(id)).findAny().orElse(null))
                                    .filter(Objects::nonNull)
                                    .collect(Collectors.toList());

                item.setGroupList(subGroups);
            });

            LambdaQueryWrapper configQuery=Wrappers.lambdaQuery(BasicStatusConfig.class)
                                            .eq(BasicStatusConfig::getStatusType,2)
                                            .eq(BasicStatusConfig::getStatus,1)
                                            .eq(BasicStatusConfig::getTenantId,KefuContext.getTid())
                                            .notIn(BasicStatusConfig::getStatusCode,"Logged Out","Available","3");//退出，空闲，忙碌
            List<BasicStatusConfig> list=basicStatusConfigMapper.selectList(configQuery);
            List<String> select=Lists.newArrayList("SUM(CASE WHEN CallStatus = '小休状态' AND onbreakkey = 2  THEN 1 ELSE 0 END ) AS idle",
                    "SUM(CASE WHEN CallStatus = '小休状态' AND onbreakkey = 3  THEN 1 ELSE 0 END ) AS busy",
                    "SUM(CASE WHEN CallStatus ='话机振铃' OR CallStatus = '呼叫中' OR CallStatus ='通话中' OR CallStatus ='保持中'  OR CallStatus ='呼入响铃' OR CallStatus ='呼入应答'   OR CallStatus ='转接操作中' OR CallStatus ='转接振铃' OR CallStatus ='转接通话中' OR CallStatus ='监听中' THEN 1 ELSE 0 END ) AS duringCall",
                    "SUM(CASE  WHEN CallStatus = '小休状态' AND onbreakkey = 1  THEN 1 ELSE 0 END ) AS aftertreatment");

            List<String> customList=list.stream().map(conf->"SUM(CASE  WHEN CallStatus = '小休状态' AND onbreakkey = '"+conf.getStatusCode()+"'  THEN 1 ELSE 0 END ) as custom_"+conf.getId()+"")
                    .collect(Collectors.toList());
            select.addAll(customList);
            QueryWrapper queryWrapper=Wrappers.query()
                    .eq("company",KefuContext.getTid())
                    .in("CCAgent",userIds)
                    .select(select);

            List<Map<String,Long>> results=callUserStatusMapper.selectMaps(queryWrapper);
            results.stream().findAny().ifPresent(map->{
                statistics.setIdle(map.get("idle"));
                statistics.setBusy(map.get("busy"));
                statistics.setDuringCall(map.get("duringcall"));
                statistics.setAftertreatment(map.get("aftertreatment"));
                Map<String,Long> custom=Maps.newHashMap();
                list.forEach(conf-> custom.put(conf.getStatusName(),map.get("custom_"+conf.getId())));
                statistics.setCustom(custom);

            });
        }

        return CallUserStatusWrapper.builder()
                .list(callUserStatuses)
                .statistics(statistics)
                .build();
    }


    public List<CallQueueGroup> callQueueGroup() {
        List<CallQueueGroup> list = new ArrayList<>();
        String tid = KefuContext.getTid();
        List<SysGroup> sysGroupList = sysGroupMapper.selectList(Wrappers.lambdaQuery(SysGroup.class)
                .eq(SysGroup::getGroupType, 1).eq(SysGroup::getTenantId, tid).orderByAsc(SysGroup::getCreateTime));
        sysGroupList.forEach(sysGroup -> {
            CallQueueGroup queue = new CallQueueGroup();
            queue.setGroupId(sysGroup.getGroupId());
            queue.setGroupName(sysGroup.getGroupName());
            Object queueCount = redisTemplate1.opsForHash().get(CALL_QUEUE_GROUP + tid, sysGroup.getGroupId());
            if (queueCount != null) {
                queue.setQueueSize(Integer.parseInt(queueCount.toString()));
            }
            list.add(queue);
        });
        return list.stream().sorted(Comparator.comparingInt(CallQueueGroup::getQueueSize).reversed()).collect(Collectors.toList());
    }

    public List<CallNumberStatisticsVo> callNumber(CallNumberStatisticsSearchVo param) {
        if (null != param.getStart() && null != param.getEnd()) {
            param.setStartTime(DateUtil.format(new Date(param.getStart()), "yyyy-MM-dd HH:mm:ss"));
            param.setEndTime(DateUtil.format(new Date(param.getEnd()), "yyyy-MM-dd HH:mm:ss"));
        }
        List<CallNumberStatisticsVo> list = callMakeCallMapper.callNumberStatistics(param, KefuContext.getKefuContext().getTenantId());
        NumberFormat nt = NumberFormat.getPercentInstance();
        nt.setMinimumFractionDigits(2);

        list.forEach(
                number -> {
                    if (number.getCallOutTotal() == 0) {
                        number.setCallThroughRate("0.00%");
                    }
                    number.setCallThroughRate(nt.format(number.getCallThroughTotal() / (double) number.getCallOutTotal()));
                }
        );
        return list;
    }

    public void numberExport(CallNumberStatisticsSearchVo param, HttpServletResponse response) throws IOException {
        List<CallNumberStatisticsVo> numberList = callNumber(param);
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("号码"), msg("归属地"), msg("添加时间"), msg("外呼总数"), msg("接听数"), msg("未接通数"), msg("接通率"), msg("状态"), msg("计费时长(分钟)"), msg("通话时长(秒)")};
        exportList.add(title);
        for (CallNumberStatisticsVo vo : numberList) {
            Object[] row = {vo.getNumber(), vo.getArea(), vo.getCreateTime(), vo.getCallOutTotal(), vo.getCallThroughTotal(), vo.getCallNotThroughTotal(), vo.getCallThroughRate(), vo.getNumberState(), vo.getChargeTime(), vo.getCallTimeTotal()};
            exportList.add(row);
        }
        csvWriter(exportList, response);
    }

    public List<CallOverviewVo> callOverviewList(CallOverviewSearchVo param) {
        //判断是日周统计还是月统计
        ArrayList<CallOverviewVo> callOverviewVos = new ArrayList<>();
        DateTime startDate = DateUtil.parse(DateUtil.format(new Date(param.getQueryTimeStart()), "yyyy-MM-dd"));
        DateTime endDate = DateUtil.parse(DateUtil.format(new Date(param.getQueryTimeEnd()), "yyyy-MM-dd"));
        DateTime begin;
        DateTime end;
        Map<String, Object> queryParam = Maps.newHashMap();
        if (param.statisticsType.equals(1) || param.statisticsType.equals(3)) {
            //获取开始时间
            begin = DateUtil.beginOfDay(startDate.toJdkDate());
            //获取结束时间
            end = DateUtil.endOfDay(endDate.toJdkDate());
            if (param.statisticsType.equals(3)) {
                begin = new DateTime(getFirstDayOfWeek(begin));
                end = new DateTime(getLastDayOfWeek(end));
            }
            queryParam.put("startTime", Timestamp.valueOf(begin.toString()));
            queryParam.put("endTime", Timestamp.valueOf(end.toString()));
            queryParam.put("tenantId", KefuContext.getTid());
            queryParam.put("agent", "");
            queryParam.put("statisticsType", param.getStatisticsType());
            List<Map<String, Object>> result1 = callMakeCallMapper.callOutOverview(queryParam);
            List<Map<String, Object>> result2 = callStartMapper.callInOverview(queryParam);
            for (int i = 0; i < result2.size(); i++) {
                Map<String, Object> outResult = result1.get(i);
                Map<String, Object> inResult = result2.get(i);
                inResult.putAll(outResult);
                CallOverviewVo workVo = BeanUtil.toBean(inResult,
                        CallOverviewVo.class, CopyOptions.create().ignoreCase());
                workVo.setOutCallTalkTimeAvg(DivUtil.div(workVo.getOutCallTalkTime(), workVo.getOutCallSuccessNumber()));
                workVo.setCallInTalkTimeAvg(DivUtil.div(workVo.getCallInTalkTime(), workVo.getAgentAnswerNumber()));
                callOverviewVos.add(workVo);
            }

        } else {
            //获取开始时间
            begin = DateUtil.beginOfMonth(startDate.toJdkDate());
            //获取结束时间
            end = DateUtil.endOfMonth(endDate.toJdkDate());
            queryParam.put("startTime", Timestamp.valueOf(begin.toString()));
            queryParam.put("endTime", Timestamp.valueOf(end.toString()));
            queryParam.put("tenantId", KefuContext.getTid());
            queryParam.put("agent", "");
            queryParam.put("statisticsType", param.getStatisticsType());
            List<Map<String, Object>> result1 = callMakeCallMapper.callOutOverview(queryParam);
            List<Map<String, Object>> result2 = callStartMapper.callInOverview(queryParam);
            for (int i = 0; i < result2.size(); i++) {
                Map<String, Object> outResult = result1.get(i);
                Map<String, Object> inResult = result2.get(i);
                inResult.putAll(outResult);
                CallOverviewVo workVo = BeanUtil.toBean(inResult,
                        CallOverviewVo.class, CopyOptions.create().ignoreCase());
                workVo.setOutCallTalkTimeAvg(DivUtil.div(workVo.getOutCallTalkTime(), workVo.getOutCallSuccessNumber()));
                workVo.setCallInTalkTimeAvg(DivUtil.div(workVo.getCallInTalkTime(), workVo.getAgentAnswerNumber()));
                callOverviewVos.add(workVo);
            }
        }
        return callOverviewVos;
    }

    /**
     * 获取指定日期所在周的周一 * * @param date 日期
     */
    public Date getFirstDayOfWeek(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            c.add(Calendar.DAY_OF_MONTH, -1);
        }
        c.add(Calendar.DATE, c.getFirstDayOfWeek() - c.get(Calendar.DAY_OF_WEEK) + 1);
        return c.getTime();
    }

    /**
     * 获取指定日期所在周的周日 * * @param date 日期
     */
    public Date getLastDayOfWeek(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        // 如果是周日直接返回
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            return date;
        }
        //System.out.println(c.get(Calendar.DAY_OF_WEEK));
        c.add(Calendar.DATE, 7 - c.get(Calendar.DAY_OF_WEEK) + 1);
        return c.getTime();
    }

    public List<CallSkillsetsWorkLoadVo> callSkillsetsWorkloadList(CallSkillsetsWorkloadSearchVo param) {
        List<CallSkillsetsWorkLoadVo> workList = new ArrayList<>();
        LambdaQueryWrapper<SysGroup> wrapper = Wrappers.lambdaQuery(SysGroup.class);
        wrapper.eq(SysGroup::getTenantId, KefuContext.getTid());
        wrapper.eq(SysGroup::getGroupType, 1);
        if (StrUtil.isNotBlank(param.getGroupId())) {
            wrapper.in(SysGroup::getGroupId, Arrays.asList(param.getGroupId().split(",")));
        }
        List<SysGroup> sysGroups = sysGroupMapper.selectList(wrapper);
        String endTime = DateUtil.format(new Date(param.getQueryTimeEnd()), "yyyy-MM-dd HH:mm:ss");
        Map<String, Object> staticQuery = Maps.newHashMap();
        staticQuery.put("startTime", DateUtil.beginOfDay(DateUtil.date(param.getQueryTimeStart())));
        staticQuery.put("endTime", new Date(param.getQueryTimeEnd()));
        staticQuery.put("tenantId", KefuContext.getTid());
        if (StrUtil.isNotBlank(param.getGroupId())) {
            staticQuery.put("groupIds", Arrays.asList(param.getGroupId().split(",")));
        }
        if (Timestamp.valueOf(endTime).getTime() > DateUtil.beginOfDay(new Date()).getTime()) {
            staticQuery.put("today", true);
        }
        staticQuery.put("startTime", new Date(param.getQueryTimeStart()));
        List<Map<String, Object>> overviewSkillsets = callStartMapper.callOverviewSkillsets(staticQuery);
        List<Map<String, Object>> callIns = callStartMapper.staticsSkillsetsCallInList(staticQuery);
        for (SysGroup sysGroup: sysGroups) {
            CallSkillsetsWorkLoadVo workVo = BeanUtil.toBean(sysGroup, CallSkillsetsWorkLoadVo.class);
            Map<String, Object> in = callIns.stream().filter(map -> map.get("groupid").equals(workVo.getGroupId()))
                    .findFirst().orElse(null);
            if (in != null && in.size() > 0) {
                BigDecimal callInNumber = BigDecimalUtil.get(in.get("callinnumber"));
                BigDecimal agentNoAnswerNumber = BigDecimalUtil.get(in.get("agentnoanswernumber"));
                BigDecimal agentAnswerNumber = BigDecimalUtil.get(in.get("agentanswernumber"));
                BigDecimal agentAnswer15Number = BigDecimalUtil.get(in.get("agentanswer15number"));
                BigDecimal callInTalkTime = BigDecimalUtil.get(in.get("callintalktime"));
                BigDecimal callInQueueNumber = BigDecimalUtil.get(in.get("callinqueuelnumber"));
                BigDecimal callInQueuelFailNumber = BigDecimalUtil.get(in.get("callinqueuelfailnumber"));
                BigDecimal callInQueuelSuccessNumber = BigDecimalUtil.get(in.get("callinqueuelsuccessnumber"));
                BigDecimal time15GiveUpNumber = BigDecimalUtil.get(in.get("time15giveupnumber"));
                BigDecimal callInHoldNumber = BigDecimalUtil.get(in.get("callinholdnumber"));
                BigDecimal callInHoldTime = BigDecimalUtil.get(in.get("callinholdtime"));
                BigDecimal callInRingNumber = BigDecimalUtil.get(in.get("callinringnumber"));
                workVo.setCallInNumber(callInNumber.intValue());
                workVo.setCallInRingNumber(callInRingNumber.intValue());
                workVo.setAgentNoAnswerNumber(agentNoAnswerNumber.intValue());
                workVo.setAgentAnswerNumber(agentAnswerNumber.intValue());
                workVo.setAgentAnswerRatio(DivUtil.percent(agentAnswerNumber.intValue(), callInRingNumber.intValue()) == null ? "0" : DivUtil.percent(agentAnswerNumber.intValue(), callInRingNumber.intValue()));
                workVo.setAgentAnswer15Number(agentAnswer15Number.intValue());
                workVo.setAgentAnswer15Ratio(DivUtil.percent(agentAnswer15Number.intValue(), callInRingNumber.intValue()) == null ? "0" : DivUtil.percent(agentAnswer15Number.intValue(), callInRingNumber.intValue()));
                workVo.setCallInTalkTime(callInTalkTime.longValue());
                workVo.setCallInTalkTimeAvg(DivUtil.div(callInTalkTime.longValue(), agentAnswerNumber.intValue()));
                workVo.setCallInQueuelNumber(callInQueueNumber.intValue());
                workVo.setCallInQueuelFailNumber(callInQueuelFailNumber.intValue());
                workVo.setCallInQueuelSuccessNumber(callInQueuelSuccessNumber.intValue());
                workVo.setTime15GiveUpNumber(time15GiveUpNumber.intValue());
                workVo.setTime15GiveUpRatio(DivUtil.percent(time15GiveUpNumber.intValue(), callInQueuelFailNumber.intValue()) == null ? "0" : DivUtil.percent(time15GiveUpNumber.intValue(), callInQueuelFailNumber.intValue()));
                workVo.setCallInHoldNumber(callInHoldNumber.intValue());
                workVo.setCallInHoldTime(callInHoldTime.longValue());
            }
            Map<String, Object> skillsetsMap = overviewSkillsets.stream().filter(map -> map.get("groupid").equals(workVo.getGroupId())).findFirst().orElse(null);
            if (skillsetsMap != null && skillsetsMap.size() > 0) {
                workVo.setCallInTotal(Convert.toInt(skillsetsMap.get("callintotal")));
                workVo.setCallInNoRing(Convert.toInt(skillsetsMap.get("callinnoring")));
                workVo.setCallInAgentRingCount(Convert.toInt(skillsetsMap.get("callinagentringcount")));
                workVo.setCallInAgentTalkCount(Convert.toInt(skillsetsMap.get("callinagenttalkcount")));
                workVo.setCallInAgentTalkCount(Convert.toInt(skillsetsMap.get("callinagenttalkcount")));
                workVo.setCallInBillingTalkTime(Convert.toInt(skillsetsMap.get("callinbillingtalktime")));
            }
            workList.add(workVo);
        }
        workList.sort(Comparator.comparing(CallSkillsetsWorkLoadVo::getCallInNumber, Comparator.reverseOrder()));
        return workList;
    }

    public void exportCallSkillsetsWorkload(CallSkillsetsWorkloadSearchVo param, HttpServletResponse response) throws IOException {
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {msg("技能组id"), msg("技能组"), msg("呼入总数"),
                msg("呼入排队数"), msg("呼入排队放弃数")
                , msg("呼入排队接听数"), msg("呼入振铃数"), msg("呼入接听数"),
                msg("呼入未接听"),
                msg("呼入接听率"), msg("振铃15秒接听数"), msg("振铃15秒接听率"),
                msg("呼入通话总时长"),
                msg("呼入通话平均时长")
        };
        exportList.add(title);
        List<CallSkillsetsWorkLoadVo> list = callSkillsetsWorkloadList(param);
        list.forEach(work -> {
            Object[] row = {
                    work.getGroupId(),
                    work.getGroupName(),
                    work.getCallInNumber(),
                    work.getCallInQueuelNumber(),
                    work.getCallInQueuelFailNumber(),
                    work.getCallInQueuelSuccessNumber(),
                    work.getCallInRingNumber(),
                    work.getAgentAnswerNumber(),
                    work.getAgentNoAnswerNumber(),
                    work.getAgentAnswerRatio(),
                    work.getAgentAnswer15Number(),
                    work.getAgentAnswer15Ratio(),
                    converTime(work.getCallInTalkTime()),
                    converTime(work.getCallInTalkTimeAvg())
            };
            exportList.add(row);
        });
        csvWriter(exportList, response);
    }

    private String converTime(long seconds) {
        long hours = seconds / 3600; // 转换为小时数
        long minutes = (seconds - hours * 3600) / 60; // 转换为分钟数
        long remainingSeconds = seconds - hours * 3600 - minutes * 60; // 剩余的秒数
        if (hours != 0) {
            return String.format("%02d", hours) + ":" + String.format("%02d", minutes) + ":" + String.format("%02d", remainingSeconds);
        } else {
            return String.format("%02d", minutes) + ":" + String.format("%02d", remainingSeconds);
        }
    }

    public void callOverviewListExport(CallOverviewSearchVo param, HttpServletResponse response) throws IOException {
        List<Object[]> exportList = new ArrayList<>();
        Object[] title = {
                msg("时间"),
                msg("外呼数量"),
                msg("外呼接听"),
                msg("外呼接听率"),
                msg("外呼未接听"),
                msg("外呼通话总时长"),
                msg("外呼计费时长"),
                msg("外呼通话平均时长"),
                msg("外呼通话保持时间"),
                msg("外呼通话保持次数"),
                msg("外呼振铃坐席数"),
                msg("外呼接听坐席数"),
                msg("呼入总数"),
                msg("呼入未振铃"),
                msg("呼入振铃"),
                msg("呼入接听"),
                msg("呼入接听率"),
                msg("呼入未接听"),
                msg("呼入15秒接听数"),
                msg("呼入15秒接听率"),
                msg("呼入通话总时长"),
                msg("呼入通话总计费时长单位分钟"),
                msg("呼入通话平均时长"),
                msg("呼入排队"),
                msg("呼入排队未接听"),
                msg("呼入通话保持次数"),
                msg("呼入通话保持时间"),
                msg("呼入振铃座席数"),
                msg("呼入接听座席数")
        };
        exportList.add(title);
        List<CallOverviewVo> overviewVos = callOverviewList(param);
        for (CallOverviewVo callOverviewVo : overviewVos) {
            Object[] row = {
                    callOverviewVo.getResultDate(),
                    callOverviewVo.getOutCallNumber(),
                    callOverviewVo.getOutCallSuccessNumber(),
                    callOverviewVo.getOutCallSuccessRatio(),
                    callOverviewVo.getOutCallFailNumber(),
                    DateUtil.secondToTime(Integer.parseInt(String.valueOf(callOverviewVo.getOutCallTalkTime()))),
                    callOverviewVo.getOutCallBillingTalkTime(),
                    DateUtil.secondToTime(Integer.parseInt(String.valueOf(callOverviewVo.getOutCallTalkTimeAvg()))),
                    DateUtil.secondToTime(Integer.parseInt(String.valueOf(callOverviewVo.getOutCallHoldTime()))),
                    callOverviewVo.getOutCallHoldNumber(),
                    callOverviewVo.getOutCallAgentRingCount(),
                    callOverviewVo.getOutCallAgentTalkCount(),
                    callOverviewVo.getCallInTotal(),
                    callOverviewVo.getCallInNoRing(),
                    callOverviewVo.getCallInNumber(),
                    callOverviewVo.getAgentAnswerNumber(),
                    callOverviewVo.getAgentAnswerRatio(),
                    callOverviewVo.getAgentNoAnswerNumber(),
                    callOverviewVo.getAgentAnswer15Number(),
                    callOverviewVo.getAgentAnswer15Ratio(),
                    DateUtil.secondToTime(Integer.parseInt(String.valueOf(callOverviewVo.getCallInTalkTime()))),
                    callOverviewVo.getCallInBillingTalkTime(),
                    DateUtil.secondToTime(Integer.parseInt(String.valueOf(callOverviewVo.getCallInTalkTimeAvg()))),
                    callOverviewVo.getCallInQueueNumber(),
                    callOverviewVo.getCallInQueuelFailNumber(),
                    callOverviewVo.getCallInHoldNumber(),
                    DateUtil.secondToTime(Integer.parseInt(String.valueOf(callOverviewVo.getCallInHoldTime()))),
                    callOverviewVo.getCallInAgentRingCount(),
                    callOverviewVo.getCallInAgentTalkCount()};
            exportList.add(row);
        }
        csvWriter(exportList, response);
    }

    /**
     * 坐席状态统计导出
     */
    public void exportCallAgentStatusRpt(CallAgentWorkLoadSearchVo param, HttpServletResponse response) throws IOException {
        param.setPageNo(1);
        param.setPageSize(1000);
        Page<CallAgentWorkLoadVo> callWorkloadList = callWorkloadList(param);
        List<List<String>> exportList = new ArrayList<>();
        List<String> title = Lists.newArrayList();
        title.add(msg("客服名称"));
        title.add(msg("登录时长"));
        title.add(msg("空闲时长"));
        title.add(msg("空闲占比"));
        List<BasicStatusConfig> basicStatusConfigs = callAgentStatusTitle();
        basicStatusConfigs.forEach(config -> {
            title.add(msg(config.getStatusName()));
            title.add(msg(config.getStatusName() + "占比"));
        });
        title.add(msg("呼入通话总时长"));
        title.add(msg("呼入通话平均时长"));
        title.add(msg("外呼通话总时长"));
        title.add(msg("外呼通话平均时长"));
        exportList.add(title);
        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
        formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
        for (CallAgentWorkLoadVo i : callWorkloadList.getRecords()) {
            List<String> row = Lists.newArrayList();
            row.add(i.getAgentName());
            row.add(formatter.format((Objects.isNull(i.getOnlineTime()) ? 0 : i.getOnlineTime()) * 1000));
            row.add(formatter.format((Objects.isNull(i.getIdeTime()) ? 0 : i.getIdeTime()) * 1000));
            row.add(i.getIdeRatio());
            List<CallAgentAuxWorkLoadVo> workLoadVoList = i.getCallAgentAuxWorkLoadVoList();
            if (CollUtil.isEmpty(workLoadVoList)) {
                basicStatusConfigs.forEach(config -> {
                    row.add("0");
                    row.add(formatter.format(0));
                });
            } else {
                workLoadVoList.forEach(workLoadVo -> {
                    row.add(formatter.format((Objects.isNull(workLoadVo.getAuxtime()) ? 0 : workLoadVo.getAuxtime()) * 1000));
                    row.add(Objects.isNull(workLoadVo.getAuxRatio()) ? "--" : workLoadVo.getAuxRatio());
                });
            }
            row.add(formatter.format((Objects.isNull(i.getCallInTalkTime()) ? 0 : i.getCallInTalkTime()) * 1000));
            row.add(formatter.format((Objects.isNull(i.getCallInTalkTimeAvg()) ? 0 : i.getCallInTalkTimeAvg()) * 1000));
            row.add(formatter.format((Objects.isNull(i.getOutCallTalkTime()) ? 0 : i.getOutCallTalkTime()) * 1000));
            row.add(formatter.format((Objects.isNull(i.getOutCallTalkTimeAvg()) ? 0 : i.getOutCallTalkTimeAvg()) * 1000));
            exportList.add(row);
        }
        csvWriter(exportList, response);
    }

    public List<BasicStatusConfig> callAgentStatusTitle() {
        List<BasicStatusConfig> basicStatusConfigs = basicStatusConfigMapper.selectList(
                Wrappers.lambdaQuery(BasicStatusConfig.class)
                .eq(BasicStatusConfig::getStatusType, 2)
                .eq(BasicStatusConfig::getTenantId, KefuContext.getTid())
                .notIn(BasicStatusConfig::getStatusCode, Lists.newArrayList("Available", "Logged Out")));
        BasicStatusConfig basicStatusConfig = new BasicStatusConfig();
        basicStatusConfig.setStatusCode("1");
        basicStatusConfig.setStatusName("话后");
        basicStatusConfigs.add(basicStatusConfig);
        return basicStatusConfigs;
    }

    public void exportCallAgentStatusLog(CallAgentStatusSearchVo param, HttpServletResponse response) throws IOException {
        param.setPageNo(1);
        param.setPageSize(1000);
        Page<CallAgentStatusVo> page = callAgentStatusList(param);
        List<List<String>> exportList = new ArrayList<>();
        List<String> title = Lists.newArrayList();
        title.add(msg("客服名称"));
        title.add(msg("状态类型"));
        title.add(msg("状态开始时间"));
        title.add(msg("状态结束时间"));
        title.add(msg("持续时间"));
        exportList.add(title);
        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
        formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
        for (CallAgentStatusVo i : page.getRecords()) {
            List<String> row = Lists.newArrayList();
            row.add(i.getAgentName());
            row.add(1 == i.getStatusType() ? "空闲" : 2 == i.getStatusType() ? i.getAuxName() : "其他");
            row.add(i.getStatusStartTime());
            row.add(i.getStatusEndTime());
            Long statusEndTime = StrUtil.isBlank(i.getStatusEndTime()) ? DateUtil.current() :
                    DateUtils.parseToTime(i.getStatusEndTime()) ;
            row.add(formatter.format(statusEndTime - DateUtils.parseToTime(i.getStatusStartTime())));
            exportList.add(row);
        }
        csvWriter(exportList, response);
    }
}
